///
// * jdbm LICENSE v1.00
// *
// * Redistribution and use of this software and associated documentation
// * ("Software"), with or without modification, are permitted provided
// * that the following conditions are met:
// *
// * 1. Redistributions of source code must retain copyright
// *    statements and notices.  Redistributions must also contain a
// *    copy of this document.
// *
// * 2. Redistributions in binary form must reproduce the
// *    above copyright notice, this list of conditions and the
// *    following disclaimer in the documentation and/or other
// *    materials provided with the distribution.
// *
// * 3. The name "jdbm" must not be used to endorse or promote
// *    products derived from this Software without prior written
// *    permission of Cees de Groot.  For written permission,
// *    please contact cg@cdegroot.com.
// *
// * 4. Products derived from this Software may not be called "jdbm"
// *    nor may "jdbm" appear in their names without prior written
// *    permission of Cees de Groot.
// *
// * 5. Due credit should be given to the jdbm Project
// *    (http://jdbm.sourceforge.net/).
// *
// * THIS SOFTWARE IS PROVIDED BY THE ndbm PROJECT AND CONTRIBUTORS
// * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
// * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
// * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// * OF THE POSSIBILITY OF SUCH DAMAGE.
// *
// * Copyright 2000 (C) Cees de Groot. All Rights Reserved.
// * Contributions are Copyright (C) 2000 by their associated contributors.
// *
// 

using System;
using System.Collections;
using SharpDBM;
using SharpDBM.recman;
using SharpDBM.helper;
using SharpDBM.btree;
using NUnit.Framework;

//*************************************************************************
//**  Included in JDMB 1.0 port to SharpDBM;  11/2013 Cyrus Neah cneah@codingreal.com
//**  SharpDBM is an independent reimplementation of the JDBM 1.0 software library  
//*************************************************************************

namespace SharpDBM.Test

.btree
{

	using RecordManager = SharpDBM.RecordManager;
	using RecordManagerFactory = SharpDBM.RecordManagerFactory;
	using LongComparator = SharpDBM.helper.LongComparator;



///
// *  Random insertion/removal test for B+Tree data structure.
// *
// *  @author <a href="mailto:boisvert@exoffice.com">Alex Boisvert</a>
// *  @version $Id: BTreeBench.java,v 1.5 2005/06/25 23:12:32 doomdark Exp $
// 
	[TestFixture]
    public class BTreeBench
	{

		internal const int ITERATIONS = 1000000;

		static void Main(string[] args)
		{

			RecordManager recman;
			BTree tree = null;

			try
			{
				recman = RecordManagerFactory.createRecordManager("test");
				tree = BTree.createInstance(recman, new LongComparator(), null, null, 32);

				Hashtable hash = new Hashtable();

				for (int i=0; i<ITERATIONS; i++)
				{
					long random = (long)(new Random(0).Next(64000));

					if ((i % 5000) == 0)
					{
						Console.WriteLine("Iterations=" + i + " Objects=" + tree.size());
						recman.commit();
					}
					if (hash[random] == null)
					{
					//System.out.println( "Insert " + random );
						hash[random] = random;
						tree.insert(random, random, false);
					}
					else
					{
					//System.out.println( "Remove " + random );
						hash.Remove(random);
						object removed = (object) tree.remove(random);
						if ((removed == null) || (! removed.Equals(random)))
						{
							throw new Exception("Remove expected " + random + " got " + removed);
						}
					}
				// tree.assertOrdering();
					compare(tree, hash);
				}

				recman.close();
						}
			catch (System.Exception except)
			{
				Console.WriteLine(except.StackTrace);
			}
		}

		internal static long random(int min, int max)
		{
			return (long) Math.Round((new Random()).NextDouble() * (max-min) + min);
		}

 
//
		internal static void compare(BTree tree, Hashtable hash)
		{
			
			

			if (tree.size() != hash.Count)
			{
				throw new Exception("Tree size " + tree.size() + " Hash size " + hash.Count);
			}

			
			foreach (DictionaryEntry v in hash)
			{
                object key = (object)v.Key;
				object hashValue = hash[key];
				object treeValue = tree.find(key);
				if (! hashValue.Equals(treeValue))
				{
					Console.WriteLine("Compare expected " + hashValue + " got " + treeValue);
					NUnit.Framework.Assert.Fail("Compare NUnit.Framework.Assert.Failed");
				}
			}
			
		}

	}

}